﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Guoc.BigMall.Infrastructure.WeChat.Entitys;
using System.Net.Http;
using Newtonsoft.Json;
using System.Collections.Specialized;
using System.Net.Http.Headers;
using Guoc.BigMall.Infrastructure.Log;
using Guoc.BigMall.Infrastructure.WeChat.JsSdk;

namespace Guoc.BigMall.Infrastructure.WeChat
{
   public class WeChatApi
    {
        /// <summary>
        /// 获取凭证接口
        /// </summary>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥，既appsecret</param>
        /// <returns></returns>
        public static AccessTokenResult GetToken(string appid, string secret)
        {
            //注意：此方法不能再使用ApiHandlerWapper.TryCommonApi()，否则会循环
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",
                                    appid, secret);

            return Get<AccessTokenResult>(url); 
        }

        /// <summary>
        /// 用户信息接口 （需要用户关注才能拉取信息）
        /// </summary>
        /// <param name="accessToken">接口访问的通用accessToken</param>
        /// <param name="openId"></param>
        /// <returns></returns>
        public static WeChatUserInfo GetUserInfo(string accessToken, string openId)
        {
            var url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN";
            url = string.Format(url, accessToken, openId);

            return Get<WeChatUserInfo>(url);
        }



        /// <summary>
        /// 用户同意授权后，拉取用户个人信息(不需要关注)
        /// </summary>
        /// <param name="accessToken">通过code 换取 的accesstoken，授权专用accessToken </param>
        /// <param name="openId"></param>
        /// <returns></returns>
        public static WeChatUserInfo GetUserInfoNeedAuthorization(string accessToken,string openId)
        {
            var url = "https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN";
            url = string.Format(url, accessToken, openId);

            return Get<WeChatUserInfo>(url);
        }

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="accessToken">AccessToken</param>
        /// <param name="menuJson">菜单json</param>
        /// <returns></returns>
        public static ResponseResult CreateMenu(string accessToken, string menuJson)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}",accessToken);
            return PostJson<ResponseResult>(url, menuJson);
        }

        /// <summary>
        ///  网页静默授权接口，获取accesstoken 和 openid
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="secret"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public static AccessTokenWeb GetAccessTokenByCode(string appid, string secret, string code)
        { 
            var url=string.Format(@"https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code",
                                  appid,secret,code);
            return Get<AccessTokenWeb>(url);
        }

        /// <summary>
        ///  静默授权链接
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="returnUrl"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public static string Url_Snsapi_base(string appid,string returnUrl,string state)
        {
            returnUrl= System.Web.HttpUtility.UrlEncode(returnUrl, System.Text.Encoding.UTF8);
            var url = string.Format(@"https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base&state={2}#wechat_redirect",
                appid,returnUrl,state);
            return url;
        }
        /// <summary>
        ///  需要用户同意的授权链接
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="returnUrl"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public static string Url_Snsapi_userinfo(string appid, string returnUrl, string state)
        {
            returnUrl = System.Web.HttpUtility.UrlEncode(returnUrl, System.Text.Encoding.UTF8);
            var url = string.Format(@"https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state={2}#wechat_redirect",
                appid, returnUrl, state);
            return url;
        }

        /// <summary>
        ///  调用jsSDK 需要的 票据接口
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public static JsTicketResult GetJsTicket(string accessToken) {
            var url = string.Format(@"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi",
                                 accessToken);
            return Get<JsTicketResult>(url);
        } 


        private static T Get<T>(string url)
        {
            var log= AppContext.Current.Resolve<ILogger>();
            try
            {
                log.Info("request api:{0}", url);
                using (HttpClient client = new HttpClient())
                {
                    var response = client.GetStringAsync(url).Result;
                    log.Info("response :{0}", response);
                    var model = JsonConvert.DeserializeObject<T>(response);
                    return model;
                }
            }
            catch (Exception ex)
            {                
                throw ex;
            }
        }             
        
        private static T Post<T>(string url, List<KeyValuePair<string, string>> parameters)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    HttpContent content = new FormUrlEncodedContent(parameters);
                    var httpResponseMessage = client.PostAsync(url,content).Result;
                    var response = httpResponseMessage.Content.ReadAsStringAsync().Result;
                    var model = JsonConvert.DeserializeObject<T>(response);
                    return model;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private static T PostJson<T>(string url, string jsonContent)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    var bytes = System.Text.Encoding.UTF8.GetBytes(jsonContent);
                    var content = new ByteArrayContent(bytes);
                    content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
                    var response = client.PostAsync(url, content).Result;
                    var responseString = response.Content.ReadAsStringAsync().Result;
                    var model = JsonConvert.DeserializeObject<T>(responseString);
                    return model;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
